#pragma once
#include <windows.h>
#include <d3d11.h>
#include <d3dx11.h>
#include <d3dcompiler.h>
#include <xnamath.h>
#include <D3DX10math.h>
#include "D3DTransform.h"
#define Isolevel 0.5f
#define Scale 1.0f

#define CHUNK_AXIS_COUNT 1
#define CHUNK_AXIS_COUNT_SQUARED 1
class D3DVoxelConstants
{
	public:
	static const int                         BytesPerVoxel = 4;
	// the actual dimension of the array.
	static const int                         VoxelsPerChunkAxis = 33;
	// calculated from above
	static const int                         VoxelsPerChunkAxisSquared = 1089;
	static const int                         VoxelsPerChunkAxisCube = 35937;

	// visible voxel start offset and length
	static const int                         NonOverlappedVoxelCount = 32;
	static const int                         NonOverlappedVoxelStart = 0;
	// calculated from above
	static const int                         PreviousChunkTail = 1;
	static const int                         NextChunkHead = 33;

	static int CalcVoxelIndex(int x, int y, int z);
	static int CalcVerticePlaceholderIndex(int x, int y, int z);
	
	static int CalcChunkIndex(int x, int y, int z);

};

struct Voxel
{
	unsigned char cVolume;
	unsigned char cType;
	unsigned char cSubType;
	unsigned char cOwner;
	void operator=(Voxel &src);
};
struct CBWorldMatrix
{
    D3DXMATRIX matWorld;
};

class D3DVoxelChunk
{


public:
	ID3D11Device*                       m_pDevice; 
	ID3D11DeviceContext*                m_pImmediateContext;

	// per chunk data

	Voxel * m_pChunkData;
	bool m_bMarkedDirty;

	
	ID3D11Texture3D*										m_pVoxelData;
	ID3D11ShaderResourceView *					m_pVoxelTextureSRV;
	ID3D11SamplerState*									m_pVoxelSamplerLinear;
	ID3D11Buffer*												m_pVoxelMeshBuffer; // stream-out buffer

	ID3D11Buffer*												m_pVertexBuffer;
	ID3D11Buffer*												m_pIndexBuffer;

	ID3D11Buffer*												m_pVoxelMarkers;
	ID3D11Buffer*												m_pEdgeMarkers;

	ID3D11Texture3D*										m_pVertexIDVolume;
	ID3D11ShaderResourceView *					m_pVertexIDVolumeSRV;
	ID3D11RenderTargetView *						m_pVertexIDVolumeRTV;

public:
	D3DTransform						m_transform;
	ID3D11Buffer*                       m_pWorldMatrixBuffer;
	D3DVoxelChunk(ID3D11Device *, ID3D11DeviceContext *);

	// creates the following buffers
	// 1. voxel data buffer(exists as a form of texture), and the shader resource view.
	// 2. vertex buffer(placeholder for voxels),
	// 3. index buffer(same as above, not used),
	// 2. voxel mesh buffer (stream out)
	// 3. voxel mesh staging buffer(stream out's mirror for debugging, optional)
	// voxel shader texture sampler setup
	HRESULT InitBuffers(void);
	Voxel* GetVoxel(int x, int y, int z);

	// update the voxel texture with the 3d array
	void UpdateVoxelTexture(void);
	//Voxel* ReadVoxel(int x, int y, int z);

	void Release(void);

	HRESULT InitStage3Buffers(void);
	HRESULT InitIndexBuffer(UINT size);
};